package com.erji.common.mybatis.persistence;

import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.lang.reflect.Method;
import java.util.List;

public class ExtServiceImpl {
    @Autowired
    protected MapperFacade facade;
    @Autowired
    protected IdentifierGenerator identifierGenerator;

    public ExtServiceImpl() {
    }

    protected <S, D> Page<D> mapAsPage(final List<S> source, Class<D> destinationClass) {
        Page<D> destination = new Page();
        Type sourceType = TypeFactory.valueOf(Page.class, new java.lang.reflect.Type[]{this.elementTypeOf(source)});
        Type destType = TypeFactory.valueOf(Page.class, new java.lang.reflect.Type[]{destinationClass});
        this.facade.map(source, destination, sourceType, destType);
        return destination;
    }

    protected <S, D> PageInfo<D> mapAsPageInfo(final List<S> source, Class<D> destinationClass) {
        return new PageInfo(this.mapAsPage(source, destinationClass));
    }

    protected <S, D> List<D> mapAsList(List<S> sourceList, Class<D> targetClass) {
        return this.facade.mapAsList(sourceList, targetClass);
    }

    protected void afterTxCommit(final CallBackAction action) {
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                public void afterCommit() {
                    action.callback();
                }
            });
        } else {
            action.callback();
        }

    }

    private <T> Type<T> elementTypeOf(final Iterable<T> object) {
        try {
            Method iterator = object.getClass().getMethod("iterator");
            Type<Iterable<T>> type = TypeFactory.valueOf(iterator.getGenericReturnType());
            return type.getNestedType(0);
        } catch (NoSuchMethodException | SecurityException var4) {
            throw new IllegalStateException(var4);
        }
    }
}
